Skip to content

feat: migrate chat delete flow to dedicated api#1612

Merged
sweetmantech merged 3 commits intotestfrom
codex/arpit-migrate-chat-delete-endpoint
Mar 31, 2026
Merged

feat: migrate chat delete flow to dedicated api#1612
sweetmantech merged 3 commits intotestfrom
codex/arpit-migrate-chat-delete-endpoint

Conversation

@arpitgupta1214
Copy link
Copy Markdown
Collaborator

@arpitgupta1214 arpitgupta1214 commented Mar 30, 2026

Summary

  • migrate sidebar chat delete flow from local POST /api/room/delete to dedicated DELETE /api/chats
  • send bearer auth from frontend using useAccessToken
  • support API override in delete flow using useApiOverride
  • remove local endpoint app/api/room/delete/route.ts

Validation

  • pnpm exec eslint components/Sidebar/Modals/DeleteConfirmationModal.tsx

Summary by CodeRabbit

  • Refactor

    • Deletion now uses a centralized, authenticated client flow instead of the prior local endpoint.
    • UI deletion flow updated to rely on the shared deletion helper while preserving progress and failure reporting.
  • New Features

    • Exposed a client-side deletion hook that provides an async delete action and in-flight state.
  • Bug Fixes

    • Attempts to delete while unsigned now surface a clear authentication error.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
recoup-chat Ready Ready Preview Mar 31, 2026 3:05am

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Local room-delete route removed; client DeleteConfirmationModal now uses a new useDeleteChat hook which obtains a Bearer access token and calls an external DELETE /api/chats endpoint via lib/deleteChat instead of the previous local POST route.

Changes

Cohort / File(s) Summary
Removed local API route
app/api/room/delete/route.ts
Deleted the POST handler and exported Next.js route config (dynamic, fetchCache, revalidate).
New client-side hook
hooks/useDeleteChat.ts
Added useDeleteChat() which reads an access token (usePrivy) and optional API override, exposes deleteChat(roomId) (mutateAsync) and isDeleting mapped from mutation state.
New API client util
lib/chats/deleteChat.ts
Added deleteChat(roomId, accessToken, baseUrl?) that sends `DELETE ${baseUrl
Client component update
components/Sidebar/Modals/DeleteConfirmationModal.tsx
Replaced direct fetch logic with useDeleteChat(); removed local isDeleting state; deletion loop now calls deleteChat(...) and treats thrown errors as failures while preserving progress aggregation and onDelete/onClose behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Modal as DeleteConfirmationModal
    participant Hook as useDeleteChat
    participant Auth as usePrivy (AccessTokenProvider)
    participant API as External API (/api/chats)

    Modal->>Hook: deleteChat(roomId)
    Hook->>Auth: getAccessToken()
    Auth-->>Hook: Bearer <token> or null
    alt token present
        Hook->>API: DELETE /api/chats { id: roomId } + Authorization: Bearer <token>
        API-->>Hook: 200 OK / error payload
        alt response OK
            Hook-->>Modal: resolves (void)
        else response error
            Hook-->>Modal: throws Error(result.error or fallback)
        end
    else no token
        Hook-->>Modal: throws Error("Not authenticated")
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A route retired, its echo gone,
Hooks fetch tokens at the break of dawn.
Modal tallies each chat’s last breath,
Deletions hum, errors handled with breadth.
New path, same care—order kept, not lost.

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning PR violates SOLID principles: SRP violated in error handling (improper JSON parsing on non-JSON responses), incomplete resource handling (parsing response body on success), missing abstraction for reusable HTTP patterns violating DRY, and lacks defensive checks for API response shapes. Wrap response.json() in try-catch for graceful non-JSON handling, only parse body when !response.ok, extract common HTTP patterns into reusable utility to enforce DRY and SRP principles across API calls.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/arpit-migrate-chat-delete-endpoint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Sidebar/Modals/DeleteConfirmationModal.tsx`:
- Around line 27-28: The code uses apiOverride (from useApiOverride) directly as
baseUrl (falling back to NEW_API_BASE_URL) and may send the bearer token to
attacker-controlled origins; update DeleteConfirmationModal to validate and
sanitize apiOverride before using it for authenticated requests: allow only
same-origin or a small whitelist of trusted origins (or require a relative
path), reject or ignore overrides that parse to an external origin, and ensure
when an override is rejected you fall back to NEW_API_BASE_URL; apply the same
validation wherever baseUrl is computed from useApiOverride (e.g., the other
baseUrl usages referenced).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cee8c176-93d6-4dfe-bb52-b61884a27536

📥 Commits

Reviewing files that changed from the base of the PR and between f7e799a and 3f3d341.

📒 Files selected for processing (2)
  • app/api/room/delete/route.ts
  • components/Sidebar/Modals/DeleteConfirmationModal.tsx
💤 Files with no reviewable changes (1)
  • app/api/room/delete/route.ts

@arpitgupta1214 arpitgupta1214 removed the request for review from sweetmantech March 30, 2026 18:38
@@ -48,6 +54,11 @@ const DeleteConfirmationModal = ({ isOpen, onClose, chatRoom, chatRooms, onDelet
: 'Delete';

const handleDelete = async () => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRP - Move this handleDelete function with accessToken to a standalone hook file.

- Move API call logic (auth, fetch, error handling) into hooks/useDeleteChat.ts
- DeleteConfirmationModal now delegates to the hook
- Remove dead result.message check (API returns result.error)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Returns a hook with a deleteChat function.
*/
export function useDeleteChat() {
const accessToken = useAccessToken();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace this to use the getAccessToken call directly from the Privy SDK to follow KISS principle.

const apiOverride = useApiOverride();
const baseUrl = apiOverride || NEW_API_BASE_URL;

const deleteChat = async (roomId: string): Promise<void> => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this function be more efficient written as a useMutate from tanstack?

- Use getAccessToken from Privy SDK instead of useAccessToken hook (KISS)
- Wrap deleteChat in useMutation for proper pending/error state
- Extract API call to lib/chats/deleteChat.ts (SRP)
- Remove manual isDeleting state — useMutation.isPending handles it

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
hooks/useDeleteChat.ts (1)

12-23: Restrict API override to trusted origins in production.

apiOverride (controlled via ?api=<url> query parameter) is used in both useDeleteChat and useChatTransport to override the API base URL. Both hooks attach bearer tokens to requests sent to the overridden URL without validating the domain. The current URL validation in useApiOverride only checks syntax (new URL()) and doesn't enforce a domain whitelist.

To prevent token exfiltration, either:

  1. Disable API override in production (check IS_PROD from lib/consts.ts)
  2. Implement a whitelist of allowed domains before accepting the override
  3. Remove query parameter control and limit overrides to environment variables only
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/useDeleteChat.ts` around lines 12 - 23, The apiOverride passed into
useDeleteChat (and likewise used by useChatTransport) can cause bearer tokens to
be sent to arbitrary URLs; update the logic that derives baseUrl (which
currently uses apiOverride || NEW_API_BASE_URL) to reject or ignore untrusted
overrides by checking IS_PROD from lib/consts.ts and enforcing a domain
whitelist (or disabling overrides entirely in production): modify useApiOverride
(and callers useDeleteChat/useChatTransport) to validate the override against an
allowlist of trusted origins before using apiOverride, or when IS_PROD is true
always use NEW_API_BASE_URL and never accept query-based overrides.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@hooks/useDeleteChat.ts`:
- Around line 28-32: The code in useDeleteChat.ts calls response.json()
unconditionally which will throw for 204/empty or non-JSON DELETE responses;
change the flow in the delete handler to check response.ok (or Content-Type /
Content-Length) before parsing: if (!response.ok) read and parse the body (if
present) to include error details, otherwise skip parsing for 204 and treat as
success—use the same approach as lib/messages/clientDeleteTrailingMessages.ts
and adjust the block around response and result to conditionally parse or
short-circuit on response.ok/empty body.

---

Nitpick comments:
In `@hooks/useDeleteChat.ts`:
- Around line 12-23: The apiOverride passed into useDeleteChat (and likewise
used by useChatTransport) can cause bearer tokens to be sent to arbitrary URLs;
update the logic that derives baseUrl (which currently uses apiOverride ||
NEW_API_BASE_URL) to reject or ignore untrusted overrides by checking IS_PROD
from lib/consts.ts and enforcing a domain whitelist (or disabling overrides
entirely in production): modify useApiOverride (and callers
useDeleteChat/useChatTransport) to validate the override against an allowlist of
trusted origins before using apiOverride, or when IS_PROD is true always use
NEW_API_BASE_URL and never accept query-based overrides.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fb2a264d-6d94-4be7-ac4c-b939ee291fc9

📥 Commits

Reviewing files that changed from the base of the PR and between 3f3d341 and 6e4a20f.

📒 Files selected for processing (2)
  • components/Sidebar/Modals/DeleteConfirmationModal.tsx
  • hooks/useDeleteChat.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/Sidebar/Modals/DeleteConfirmationModal.tsx

@sweetmantech sweetmantech merged commit 2e3d1f7 into test Mar 31, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants